package ru.nstu.isma.core.lang.ast.visitor;

import ru.nstu.isma.core.lang.ast.LismaBaseVisitor;
import ru.nstu.isma.core.lang.ast.LismaParser;
import ru.nstu.isma.core.hsm.*;
import ru.nstu.isma.core.hsm.exp.HMExpression;
import org.antlr.v4.runtime.misc.NotNull;

import java.util.LinkedList;
import java.util.List;

/**
 * by Alexey Bessonov
 * Date: 03.12.13
 * Time: 0:35
 */
public class PopulateExpressionVisitor extends LismaBaseVisitor<Object> {
    private HMVariableTable table;

    private HMStateAutomata automata;

    public PopulateExpressionVisitor(HMVariableTable table, HMStateAutomata automata) {
        this.table = table;
        this.automata = automata;
    }

    @Override
    public Object visitConstant(@NotNull LismaParser.ConstantContext ctx) {
        List<HMConst> consts = new LinkedList<HMConst>();
        HMExpression expr = null;
        for (int i = 0; i< ctx.getChildCount(); i++) {
            if (ctx.getChild(i) instanceof LismaParser.Var_identContext) {
                consts.add((HMConst) table.get(ctx.getChild(i).getText()));
            }
            if (ctx.getChild(i) instanceof LismaParser.ExpressionContext) {
                ExpressionVisitor ev = new ExpressionVisitor(table);
                expr = ev.visit(ctx.getChild(i));
            }
        }
        for (HMConst c : consts) {
            c.setRightPart(expr);
        }
        return null;
    }

    @Override
    public Object visitInit_cond(@NotNull LismaParser.Init_condContext ctx) {
        VariableVisitor vv = new VariableVisitor();
        String code = vv.visit(ctx.getChild(0)).getCode();
        HMDerivativeEquation equation = (HMDerivativeEquation) table.get(code);

        HMExpression expr = null;
        for (int i = 0; i< ctx.getChildCount(); i++) {
            if (ctx.getChild(i) instanceof LismaParser.ExpressionContext) {
                ExpressionVisitor ev = new ExpressionVisitor(table);
                expr = ev.visit(ctx.getChild(i));
            }
        }
        HMConst initConst = new HMConst(code + "@init_cond");
        initConst.setRightPart(expr);
        equation.setInitial(initConst);

        return null;
    }

    @Override
    public Object visitEquation(@NotNull LismaParser.EquationContext ctx) {
        VariableVisitor vv = new VariableVisitor();
        String code = vv.visit(ctx.getChild(0)).getCode();
        HMEquation equation = (HMEquation) table.get(code);

        HMExpression expr = null;
        for (int i = 0; i< ctx.getChildCount(); i++) {
            if (ctx.getChild(i) instanceof LismaParser.ExpressionContext) {
                ExpressionVisitor ev = new ExpressionVisitor(table);
                expr = ev.visit(ctx.getChild(i));
            }
        }
        equation.setRightPart(expr);
        return null;
    }

    @Override
    public Object visitState(@NotNull LismaParser.StateContext ctx) {
        // меняем таблицу переменных на ту что в состоянии
        HMState st = automata.getState( ctx.getChild(1).getText());
        PopulateExpressionVisitor visitor = new PopulateExpressionVisitor(st.getVariables(), automata);
        visitor.visit(ctx.getChild(5));
        return null;
    }
}
